// Example 3.1: Explorer 16

// Device-Specific Configuration-bit settings
// Configuration Bits
#pragma config POSCMOD  = XT       // Primary Oscillator
#pragma config FNOSC    = PRIPLL	// Oscillator Selection
#pragma config FPLLIDIV = DIV_2    // PLL Input Divider
#pragma config FPLLMUL  = MUL_20   // PLL Multiplier
#pragma config FPLLODIV = DIV_1    // PLL Output Divider
#pragma config FPBDIV   = DIV_1    // Peripheral Clock divisor
#pragma config FWDTEN   = OFF      // Watchdog Timer
#pragma config WDTPS    = PS1      // Watchdog Timer Postscale
#pragma config FCKSM    = CSDCMD   // Clock Switching & Fail Safe Monitor
#pragma config OSCIOFNC = ON       // CLKO Enable
#pragma config IESO     = OFF      // Internal/External Switch-over
#pragma config FSOSCEN  = OFF      // Secondary Oscillator Enable
#pragma config CP       = OFF      // Code Protect
#pragma config BWP      = OFF      // Boot Flash Write Protect
#pragma config PWP      = OFF      // Program Flash Write Protect
#pragma config ICESEL   = ICS_PGx2 // ICE/ICD Comm Channel Select
#pragma config DEBUG    = ON       // Debugger Disabled for Starter Kit

#include <p32xxxx.h>
#include "Gpio.h"

int main(int argc, char** argv)
{
	// **********************************************************************
	// Configure MCU
	// **********************************************************************

	DDPCONbits.JTAGEN = 0; // Disable JTAG

	// Create variables for the PORTs
	Gpio PortA(Enums::Gpio::Ports::PortA);
	Gpio PortD(Enums::Gpio::Ports::PortD);

	// Create variables for the pins of interest
	Pin LedOutputA5 = PortA.GetPin(Enums::Gpio::Pins::Number::Pin5);
	Pin LedOutputA6 = PortA.GetPin(Enums::Gpio::Pins::Number::Pin6);
	Pin SwitchInput = PortD.GetPin(Enums::Gpio::Pins::Number::Pin6);
	Pin SwitchOutput = PortA.GetPin(Enums::Gpio::Pins::Number::Pin7);

	// Set each pin direction
	LedOutputA5.SetDirection(Enums::Gpio::Pins::Direction::Output);
	LedOutputA6.SetDirection(Enums::Gpio::Pins::Direction::Output);
	SwitchInput.SetDirection(Enums::Gpio::Pins::Direction::Input);
	SwitchOutput.SetDirection(Enums::Gpio::Pins::Direction::Output);

	// Set the initial state of the pins
	LedOutputA5.ClearPin();
	LedOutputA6.SetPin();

	while (true)
	{
		// Clear the pins
		LedOutputA5.ClearPin();
		LedOutputA6.TogglePin();
		_CP0_SET_COUNT(0); // Reset CORE Timer
		while (_CP0_GET_COUNT() < 20E6)
		{
		} // Wait for 40E6 clocks (0.5s)

		// Set the pins
		LedOutputA5.SetPin();
		LedOutputA6.TogglePin();
		_CP0_SET_COUNT(0); // Reset CORE Timer
		while (_CP0_GET_COUNT() < 20E6)
		{
		} // Wait for 40E6 clocks (0.5s)

		// Get switch state. If it's pressed, illuminate the LED,
		// otherwise clear it.
		if (SwitchInput.GetPinValue() == Enums::Gpio::Pins::Value::High)
			SwitchOutput.SetPin();
		else
			SwitchOutput.ClearPin();
	}
}